# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   File Name：     origin_point_generate
   Description :
   Author :       'li'
   date：          2021/7/5
-------------------------------------------------
   Change Activity:
                   2021/7/5:
-------------------------------------------------
"""
import cv2
import numpy as np

from ...sort_points.sort_points import resort_points
from ....misc.img_io import read_img


class LineCalculation:
    def __init__(self, p0, p1):
        self.p0 = p0
        self.p1 = p1
        self.k = self._calculate_k()
        self.b = self._calculate_b()
        pass

    def _calculate_k(self):
        return (self.p0[1] - self.p1[1]) / (self.p0[0] - self.p1[0] - 10e-10)

    def _calculate_b(self):
        x, y = self.p0[0], self.p0[1]
        b = y - self.k * x
        return b

    def get_extend_point(self, x=None, y=None):
        if x is None and y is None:
            raise Exception('only one value is None')
        if x is None:
            x = (y - self.b) / (self.k - 10e-11)
            return [x, y]
        if y is None:
            y = self.k * x + self.b
            return [x, y]


class OriginPointGenerator:
    def __init__(self, contour, bbox):
        """

        :param contour:
        :param bbox:
        """
        self.contour = contour
        self.bbox = bbox
        self.top_box_p, self.right_box_p, self.down_box_p, self.left_box_p = self._load_bbox_p()
        self.contour_max_h, self.contour_min_h, self.contour_max_w, self.contour_min_w = self.__load_contour_info()
        self.top_p, self.down_p = self._load_top_down_points()
        self.left_p, self.right_p = self._load_left_right_points()

    def _load_top_down_points(self):
        cal = LineCalculation(self.top_box_p, self.down_box_p)
        min_h = self.contour_min_h - 2
        top_p = cal.get_extend_point(y=min_h)
        max_h = self.contour_max_h + 2
        down_p = cal.get_extend_point(y=max_h)
        return top_p, down_p

    def _load_left_right_points(self):
        cal = LineCalculation(self.right_box_p, self.left_box_p)
        min_w = self.contour_min_w - 2
        left_p = cal.get_extend_point(x=min_w)
        max_w = self.contour_max_w + 2
        right_p = cal.get_extend_point(x=max_w)
        return left_p, right_p

    def __load_contour_info(self):
        ws = self.contour[:, 0]
        hs = self.contour[:, 1]
        return hs.max(), hs.min(), ws.max(), ws.min()

    def get_top_point(self):
        cal = LineCalculation(self.top_box_p, self.down_box_p)
        min_h = self.contour_min_h - 2
        res = cal.get_extend_point(y=min_h)
        return res

    def get_right_point(self):
        cal = LineCalculation(self.top_box_p, self.down_box_p)
        min_h = self.contour_min_h - 2
        res = cal.get_extend_point(y=min_h)
        return res

    def get_down_point(self):
        cal = LineCalculation(self.top_box_p, self.down_box_p)
        min_h = self.contour_min_h - 2
        res = cal.get_extend_point(y=min_h)
        return res

    def get_left_point(self):
        cal = LineCalculation(self.top_box_p, self.down_box_p)
        min_h = self.contour_min_h - 2
        res = cal.get_extend_point(y=min_h)
        return res

    def _load_bbox_p(self):
        """
        :return:
        """
        top = (self.bbox[0, :] + self.bbox[1, :]) / 2
        right = (self.bbox[1, :] + self.bbox[2, :]) / 2
        down = (self.bbox[2, :] + self.bbox[3, :]) / 2
        left = (self.bbox[3, :] + self.bbox[0, :]) / 2
        return top, right, down, left

    def _load_contour_info(self):
        pass


def _get_max_size_contours(contours):
    """
    get max siz contours
    """
    return_contours = contours[0]
    length = len(contours)
    for i in range(1, length):
        ret_size = return_contours.shape[0]
        new_size = contours[i].shape[0]
        if ret_size < new_size:
            return_contours = contours[i]
    return return_contours


def _main():
    img = read_img('bg.jpg')
    bg = img.astype(np.uint8)
    ret, thresh = cv2.threshold(bg, 127, 255, 0)
    contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    if len(contours) == 0:
        return None
    if len(contours) > 1:
        contours = [_get_max_size_contours(contours)]
    bg_contour = contours[0]
    rect = cv2.minAreaRect(bg_contour)
    box = cv2.boxPoints(rect)
    box = resort_points(box)
    rr = OriginPointGenerator(bg_contour[:, 0, :], box)
    rr.get_top_point()


if __name__ == '__main__':
    _main()
